/*
 * FullBinomial.java
 *
 * Created on January 28, 2005, 1:48 PM
 */

package com.milowski.monos.binomial;

import com.milowski.monos.*;
import com.milowski.monos.monomial.*;
import org.infoset.xml.InfosetFactory;
import org.infoset.xml.ItemConstructor;
import org.infoset.xml.ItemDestination;
import org.infoset.xml.XMLException;

/**
 *
 * @author R. Alexander Milowski
 */
public class FullBinomial implements Binomial
{
   
   public short [] leading;
   public short [] trailing;
   
   /** Creates a new instance of Binomial */
   public FullBinomial(Monomial leadingTerm,Monomial trailingTerm) {
      this(leadingTerm.getValues(),trailingTerm.getValues());
   }
   
   public FullBinomial(FullBinomial b) {
      this(b.leading,b.trailing, true);
   }
   
   public FullBinomial(short [] leadingTerm, short [] trailingTerm) {
      this(leadingTerm, trailingTerm,true);
   }
   public FullBinomial(short [] leadingTerm, short [] trailingTerm,boolean copy) {
      if (copy) {
         leading = new short[leadingTerm.length];
         trailing = new short[leadingTerm.length];
         for (int i=0; i<leadingTerm.length; i++) {
            leading[i] = leadingTerm[i];
            trailing[i] = trailingTerm[i];
         }
      } else {
         leading = leadingTerm;
         trailing = trailingTerm;
      }
   }
   
   public FullBinomial(int length) {
      this.leading = new short[length];
      this.trailing = new short[length];
   }
   
   public FullBinomial(short [] compactValues) {
      this(compactValues.length);
      for (int i=0; i<compactValues.length; i++) {
         if (compactValues[i]>=0) {
            leading[i] = compactValues[i];
            trailing[i] = 0;
         } else {
            leading[i] = 0;
            trailing[i] = (short)(-compactValues[i]);
         }
      }
   }
   
   public short [] getLeadingTerm() {
      return leading;
   }
   
   public short [] getTrailingTerm() {
      return trailing;
   }
   
   public void swap() {
      short [] temp = leading;
      leading = trailing;
      trailing = temp;
   }
   
   public Monomial toLeadingMonomial() {
      Monomial a = new Monomial(leading);
      return a;
   }
   
   public Monomial toTrailingMonomial() {
      Monomial b = new Monomial(trailing);
      return b;
   }
   
   /*
   public void set(Monomial leadingTerm,Monomial trailingTerm) {
      leading = leadingTerm.getValues();
      trailing = trailingTerm.getValues();
   } */  
   public CompactBinomial toCompactBinomial() {
      return new CompactBinomial(leading,trailing);
   }
   
   public boolean equals(Object other) {
      if (!(other instanceof Binomial)) {
         return true;
      }
      Binomial bother = (Binomial)other;
      short [] otherLeading = bother.getLeadingTerm();
      short [] otherTrailing = bother.getTrailingTerm();
      if (leading.length!=otherLeading.length) {
         return false;
      }
      for (int i=0; i<otherLeading.length; i++) {
         if (leading[i]!=otherLeading[i]) {
            return false;
         }
         if (trailing[i]!=otherTrailing[i]) {
            return false;
         }
      }
      return true;
   }
   
   String format(LexOrder order,short [] values) {
      StringBuffer sb = new StringBuffer();
      boolean started = false;
      for (int i=0; i<values.length; i++) {
         if (values[i]!=0) {
            if (started) {
               sb.append('*');
            }
            started = true;
            sb.append((String)order.get(i));
            if (values[i]!=1) {
               sb.append('^');
               sb.append(Short.toString(values[i]));
            }
         }
      }
      return sb.toString();
   }
   
   public String format(LexOrder order)
   {
      return format(order,leading)+' '+format(order,trailing);
   }
   
   public String toString() {
      StringBuffer sb = new StringBuffer();
      sb.append("(list->binomial `(");
      for (int i=0; i<leading.length; i++) {
         if (i!=0) {
            sb.append(' ');
         }
         sb.append(leading[i]);
      }
      sb.append(") `(");
      for (int i=0; i<trailing.length; i++) {
         if (i!=0) {
            sb.append(' ');
         }
         sb.append(trailing[i]);
      }
      sb.append("))");
      return sb.toString();
   }
      
   public static FullBinomial toBinomial(LexOrder order,String leading,String trailing) 
      throws FormatException
   {
      FullBinomial b = new FullBinomial(order.size());
      Monomial.parseMonomial(order,b.getLeadingTerm(),leading);
      Monomial.parseMonomial(order,b.getTrailingTerm(),trailing);
      return b;
   }
   
   public void toXML(ItemDestination dest) throws XMLException {
      toXML(InfosetFactory.getDefaultInfoset().createItemConstructor(),dest);
   }

   public void toXML(ItemConstructor constructor, ItemDestination dest) throws XMLException {
      dest.send(constructor.createElement(XML.binomialName));
      dest.send(constructor.createCharacters("\n"));
      Monomial.toXML(constructor,dest,leading);
      dest.send(constructor.createCharacters("\n"));
      Monomial.toXML(constructor,dest,trailing);
      dest.send(constructor.createCharacters("\n"));
      dest.send(constructor.createElementEnd(XML.binomialName));
      dest.send(constructor.createCharacters("\n"));
   }

}
